package top.ddandang.blog.service.impl;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import top.ddandang.blog.model.pojo.Article;
import top.ddandang.blog.mapper.ArticleMapper;
import top.ddandang.blog.model.pojo.Tags;
import top.ddandang.blog.model.query.PageBean;
import top.ddandang.blog.service.ArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import top.ddandang.blog.utils.OssUtil;
import top.ddandang.blog.utils.RedisUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import top.ddandang.blog.model.vo.*;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author D
 * @since 2020-06-23
 */
@Service
@Slf4j
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private OssUtil ossUtil;

    private final String path = "blog/images/article/";

    private final String articleKey = "articleDetailVo:";

    private final String recommendKey = "recommendArticle";

    /**
     * 总文章数的key值
     */
    private final String TOTAL_ARTICLE_KEY = "totalArticle";


    @Override
    public int insertArticle(String title, String contentHtml, String contentMd, int categoryId, String description, boolean allowComment) {
        Article article = new Article()
                .setTitle(title)
                .setContentHtml(contentHtml)
                .setContentMd(contentMd)
                .setCategories(categoryId)
                .setDescription(description)
                .setAllowComment(allowComment);

        while (true) {
            if(articleMapper.insert(article) == 1) {
                break;
            }
        }
        redisUtil.increment("totalArticle", 1);
        return article.getId();
    }

    @Override
    public int updateArticle(ArticleVo articleVo) {
        UpdateWrapper<Article> updateWrapper = new UpdateWrapper<Article> ()
                .eq("id", articleVo.getArticleId())
                .set("title", articleVo.getTitle())
                .set("content_html", articleVo.getContentHtml())
                .set("content_md", articleVo.getContentMd())
                .set("description", articleVo.getDescription())
                .set("allow_comment", articleVo.getAllowComment());
        //删除缓存
        String key = articleKey + articleVo.getArticleId();
        if(redisUtil.hasKey(key)) {
            redisUtil.del(key);
        }
        return articleMapper.update(null, updateWrapper);
    }

    @Override
    public String insertImage(MultipartFile file) {
        return ossUtil.uploadImage(file, path);
    }

    @Override
    public Map<String, Object> listArticleMapByTags(PageBean pageBean, Integer tagsId) {
        PageHelper.startPage(pageBean.getPageNo(), pageBean.getPageSize());
        List<IndexVo> indexVos = articleMapper.listArticleMapByTags(tagsId);
        PageInfo<IndexVo> info = new PageInfo<> (indexVos);
        //存放文章信息 和 查询的文章总数
        Map<String, Object> infoMap = new HashMap<>();
        infoMap.put("listIndexVo", indexVos);
        infoMap.put("total", info.getTotal());
        return infoMap;
    }

    @Override
    public Map<String, Object> listIndexVo(PageBean pageBean, Map<String, Object> map) {
        long startTime = System.currentTimeMillis();
        PageHelper.startPage(pageBean.getPageNo(), pageBean.getPageSize());
        List<IndexVo> indexVos = articleMapper.listArticleMap(map);
        PageInfo<IndexVo> page = new PageInfo<> (indexVos);

        long total = 0;
        if(map.isEmpty()) {
            total = articleMapper.getArticleCount();
        }else {
            total = page.getTotal();
        }

        //存放文章信息 和 查询的文章总数
        Map<String, Object> infoMap = new HashMap<>();
        infoMap.put("listIndexVo", indexVos);
        infoMap.put("total", total);
        long endTime = System.currentTimeMillis();
        log.error("运行时间："+(endTime - startTime));
        return infoMap;
    }

    @Override
    public List<IndexVo> listIndexVoByTitle(String title) {

        Map<String, Object> map = new HashMap<>();
        map.put("title", title);
        return articleMapper.listArticleMap(map);
    }

    @Override
    public int getArticleCount() {
        int articleAmount = articleMapper.getArticleCount();
        redisUtil.set(TOTAL_ARTICLE_KEY, articleAmount);
        return articleAmount;
    }

    @Override
    public List<ClassificationVo> listClassificationVoByCategoryId(Integer categoryId) {
        return articleMapper.listClassificationVoByCategoryId(categoryId);
    }

    @Override
    public List<ClassificationVo> listClassificationVoByTagsId(Integer tagsId) {
        return articleMapper.listClassificationVoByTagsId(tagsId);
    }

    @Override
    public int removeArticleCategory(Integer articleId) {
        UpdateWrapper<Article> updateWrapper = new UpdateWrapper<> ();
        updateWrapper.eq("id", articleId)
                .set("categories", null);
        return articleMapper.update(null, updateWrapper);
    }

    @Override
    public List<ClassificationVo> listArticleCategoryIsNull() {
        return articleMapper.listArticleCategoryIsNull();
    }

    @Override
    public void addArticleCategory(Integer categoryId, Integer[] articleId) {
        Map<String, Object> map = new HashMap<> ();
        map.put("categoryId", categoryId);
        map.put("articleId", articleId);
        articleMapper.addArticleCategory(map);
    }

    @Override
    public ArticleDetailVo getArticleById(Integer articleId) {

        String key = articleKey+articleId;
        ArticleDetailVo articleDetailVo = new ArticleDetailVo();
        //如果缓存中存在则从缓存中获取
        if(redisUtil.hasKey(key)) {
            articleDetailVo = (ArticleDetailVo) redisUtil.get(key);
        }else {
            articleDetailVo = articleMapper.getArticleDetailVoById(articleId);
            List<Tags> tags = articleMapper.getTagsNameByArticleId(articleId);
            articleDetailVo.setTags(tags);
            //将数据加入到缓存中并设置时间为48小时
            redisUtil.set(key, articleDetailVo, 48);
        }
        return articleDetailVo;
    }

    @Override
    public List<Article> listArticleByCategoryId(Integer categoryId) {
        QueryWrapper<Article> queryWrapper = new QueryWrapper<Article>()
                .eq("categories", categoryId);
        return articleMapper.selectList(queryWrapper);
    }

    @Override
    public List<ManageVo> listManageVo(Map<String, Object> map) {
        return articleMapper.listManageVo(map);
    }

    @Override
    public int updateArticleAllowComment(Integer articleId, Boolean allowComment) {
        return articleMapper.update(null, new UpdateWrapper<Article>()
                .eq("id", articleId)
                .set("allow_comment", allowComment));
    }

    @Override
    public int updateArticleTop(Integer articleId, Boolean top) {
        redisUtil.del(recommendKey);
        return articleMapper.update(null, new UpdateWrapper<Article>()
                .eq("id", articleId)
                .set("topping", top));
    }

    @Override
    public int deleteArticle(Integer articleId) {
        return articleMapper.deleteById(articleId);
    }

    @Override
    public List<Article> recommendArticles() {

        List<Article> articleList = new ArrayList<>();
        if(redisUtil.hasKey(recommendKey)) {
            Map<Object, Object> map = redisUtil.hmget(recommendKey);
            for(Map.Entry<Object, Object> article:map.entrySet()){
                articleList.add((Article) article.getValue());
            }
        }else {
            articleList = articleMapper.selectList(new QueryWrapper<Article>()
            .eq("topping", 1));
            Map< String,Object> map = new HashMap<>();
            for (Article article : articleList){
                map.put(article.getId().toString(),article);
            }
            redisUtil.hmset(recommendKey,map);
        }

        return articleList;
    }


}
